#include "ringbuffer.h"

/**
 * @brief IGet the ringbuffer buffer status.
 *
 * @param rb        A pointer to the ring buffer object.
 *
 * @return Return the status.
 */
RingBuffer_State ringbuffer_status(RingBuffer_TypeDef *rb) {
    if (rb->buffer_length == rb->buffer_size) {
        return RINGBUFFER_FULL;
    } else if (rb->buffer_length == 0) {
        return RINGBUFFER_EMPTY;
    } else {
        return RINGBUFFER_HALFFULL;    
    }
}

/**
 * @brief Get the ringbuffer buffer remain to read.
 *
 * @param rb        A pointer to the ring buffer object.
 *
 * @return ringbuffer buffer remain to read.
 */
uint16_t ringbuffer_length(RingBuffer_TypeDef *rb) {
    return rb->buffer_length;
}

/**
 * @brief Initialize the ring buffer object.
 *
 * @param rb        A pointer to the ring buffer object.
 * @param pool      A pointer to the buffer.
 * @param size      The size of the buffer in bytes.
 *
 * @return Return the status.
 */
int8_t ringbuffer_init(RingBuffer_TypeDef *rb,uint8_t *pool,int16_t size) {
    if(rb == NULL) {
        return -1;
    }
    if(size == 0) {
        return -1;
    }   

    /* initialize read and write index */
    rb->read_index = 0;
    rb->write_index = 0;

    /* set buffer pool and size */
    rb->buffer_ptr = pool;
    rb->buffer_size = size;
    rb->buffer_length = 0;
    return 1;
}

/**
 * @brief Put the data into the ring buffer
 *
 * @param rb            A pointer to the ring buffer object.
 * @param ptr           A pointer to the data buffer.
 *
 * @return Return the status.
 */
int8_t ringbuffer_put(RingBuffer_TypeDef *rb,uint8_t *ptr) {
    if(rb == NULL) {
        return -1;
    }

    /* no space */
    if (ringbuffer_status(rb) == RINGBUFFER_FULL){
        return -1;
    }
    
    rb->buffer_ptr[rb->write_index] = *ptr;
    rb->write_index = (rb->write_index + 1) % rb->buffer_size;
    rb->buffer_length++;
    return 1;
}

/**
 * @brief Get the data in the ring buffer.
 *
 * @param rb        The pointer to the ring buffer object.
 * @param ptr       A pointer to the data buffer.
 *
 * @return Return the status.
 */
int8_t ringbuffer_get(RingBuffer_TypeDef *rb,uint8_t *ptr){
    if(rb == NULL) {
        return -1;
    }
    
    /* no data */
    if (ringbuffer_status(rb) == RINGBUFFER_EMPTY) {
        return -1;   
    }        
    
    *ptr = rb->buffer_ptr[rb->read_index];
    rb->read_index = (rb->read_index + 1) % rb->buffer_size;
    rb->buffer_length--;
    return 1;    
}
